//
//  NNCalendarScroView.m
//  TestObjectProduct
//
//  Created by fangshufeng on 16/9/30.
//  Copyright © 2016年 fangshufeng. All rights reserved.
//

#import "NNCalendarScroView.h"
#import "NNCalendarPageView.h"
#import "NSDate+NNDateFormat.h"
#import "NNCalendarModel.h"
#import "NNCalendarScroViewConfigs.h"
#import "NNCalendarPageHeadDemoView.h"


static NSString *NNCalendarScroViewNibWithNibNameStr = @"NNCalendarDayCell";

@interface NNCalendarScroView ()<
UIScrollViewDelegate,
NNCalendarPageViewDelegate
>

@property(nonatomic, strong) UIScrollView *backScroView;

@property(nonatomic, strong) NNCalendarPageView *currentCalendarPageView;

@property(nonatomic, strong) NNCalendarPageView *moveCalendarPageView;


@property(nonatomic, assign) int currentMonth;

@property(nonatomic, assign) int loadMonth;

@property(nonatomic,strong) NSDate *currentDate;

/**是否是初始化加载*/
@property(nonatomic, assign) BOOL isFirstLoad;


/**当前月份字符串*/
@property(nonatomic, copy) NSString *currentMonthStr;

/**当前年份字符串*/
@property(nonatomic, copy) NSString *currentYearStr;

/**当前的行数*/
@property(nonatomic, assign) int currentRow;

/**缓存算过的时间*/
@property(nonatomic, strong) NSMutableDictionary *cacheCashcalculateTimes;


@end

@implementation NNCalendarScroView

- (instancetype)initWithDefaultContent {
    return  [self initWithDefaultContentBeginCalendar:NNCalendarScroViewBeginDaySunday];
}
- (instancetype)initWithNibNameStr:(NSString *)nibWithNibNameStr cellWithReuseIdentifier:(NSString *)cellWithReuseIdentifier {
    
    return [self initWithNibNameStr:nibWithNibNameStr cellWithReuseIdentifier:cellWithReuseIdentifier calendar:NNCalendarScroViewBeginDaySunday];
}

- (instancetype)initWithRegisterClassName:(NSString *)className cellWithReuseIdentifier:(NSString *)cellWithReuseIdentifier {
    
    return [self initWithRegisterClassName:className cellWithReuseIdentifier:cellWithReuseIdentifier calendar:NNCalendarScroViewBeginDaySunday];
}

- (instancetype)initWithDefaultContentBeginCalendar:(NNCalendarScroViewBeginDay)calendarScroViewBeginDay {
    return [self initWithNibNameStr:nil cellWithReuseIdentifier:nil calendar:calendarScroViewBeginDay];
}
- (instancetype)initWithNibNameStr:(NSString *)nibWithNibNameStr cellWithReuseIdentifier:(NSString *)cellWithReuseIdentifier calendar:(NNCalendarScroViewBeginDay)calendarScroViewBeginDay{
    if (self = [super init]) {
        _calendarScroViewBeginDay = calendarScroViewBeginDay;
        _nibWithNibNameStr = nibWithNibNameStr ? nibWithNibNameStr : NNCalendarScroViewNibWithNibNameStr;
        _cellWithReuseIdentifier = cellWithReuseIdentifier ? cellWithReuseIdentifier : NNCalendarScroViewNibWithNibNameStr;
        [self configSubViews];
    }
    return self;
}

- (instancetype)initWithRegisterClassName:(NSString *)className cellWithReuseIdentifier:(NSString *)cellWithReuseIdentifier calendar:(NNCalendarScroViewBeginDay)calendarScroViewBeginDay {
    if (self = [super init]) {
        _calendarScroViewBeginDay = calendarScroViewBeginDay;
        _registerClassName = className;
        _cellWithReuseIdentifier = cellWithReuseIdentifier;
        [self configSubViews];
    }
    return self;
}
- (void)configSubViews {

    
    self.currentDate = [NSDate date];
    self.dateFormat = @"yyyy-MM";
    
    [self addSubview:self.backScroView];
    
    [self.backScroView addSubview:self.currentCalendarPageView];
    [self.backScroView addSubview:self.moveCalendarPageView];
}

- (void)willMoveToSuperview:(UIView *)newSuperview {
    [super willMoveToSuperview:newSuperview];
    if (newSuperview) {
        self.isFirstLoad = YES;
        //1.构造数据
        self.currentCalendarPageView.pageItems = [self configData];
        [self sendMessageTodelegate];
        //2.布局子控件
        [self updateSubviewFrame];
        self.isFirstLoad = NO;
    }
}
- (void)updateSubviewFrame {
    //计算行数
    int row = (self.currentCalendarPageView.pageItems.count - 1) / KNNCalendarPageViewColumn + 1;
    
    CGFloat updateHeight = row * KNNCalendarPageViewVerticalMargin + 2 * KNNCalendarPageViewSectionMargin + row * [self.currentCalendarPageView itemHeightWithWidth:self.bounds.size.width];
    
    if (self.currentRow != row) {
        if (self.isFirstLoad) {
            self.frame = CGRectMake(0, 0, self.bounds.size.width, updateHeight + KNNCalendarPageViewHeadViewHeight);
            self.backScroView.frame = self.bounds;
            self.backScroView.contentOffset = CGPointMake([self backScroViewWidth], 0);
            self.backScroView.contentSize = CGSizeMake([self backScroViewWidth] * 3, 0);
            self.currentCalendarPageView.frame = CGRectMake([self backScroViewWidth], 0, [self backScroViewWidth], [self backScroViewHeight]);
        }else {
            [UIView animateWithDuration:KNNCalendarScroViewDuration animations:^{
                self.frame = CGRectMake(0, 0, self.bounds.size.width, updateHeight  + KNNCalendarPageViewHeadViewHeight);
                self.backScroView.frame = self.bounds;
                self.backScroView.contentOffset = CGPointMake([self backScroViewWidth], 0);
                self.backScroView.contentSize = CGSizeMake([self backScroViewWidth] * 3, 0);
                self.currentCalendarPageView.frame = CGRectMake([self backScroViewWidth], 0, [self backScroViewWidth], [self backScroViewHeight]);
                
            }];
        }
    }
    self.currentRow = row;
}
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
    if (self.isFirstLoad) {
        return;
    }
    scrollView.contentOffset.x >= [self backScroViewWidth] ? [self loadNextMonth] : [self loadLastMonth];
}
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {//手滑
    [self resetScroll];
}

- (void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView {//代码滑动
    [self resetScroll];
}

- (void)loadNextMonth {
    self.moveCalendarPageView.frame = CGRectMake([self backScroViewWidth] * 2, 0, [self backScroViewWidth], [self backScroViewHeight]);
    
    self.loadMonth = self.currentMonth + 1;
    self.moveCalendarPageView.pageItems =  [self configData];
}
- (void)loadLastMonth {
    self.moveCalendarPageView.frame = CGRectMake(0, 0, [self backScroViewWidth], [self backScroViewHeight]);
    self.loadMonth = self.currentMonth - 1;
    self.moveCalendarPageView.pageItems =  [self configData];
}
- (NSMutableArray *)configData {
    

    NSDate *monthDate =  [self.currentDate  dayInTheFollowingMonth:self.loadMonth];//表示下个月的第一天
    
    NSDateComponents *nowComponents = [monthDate getYMDComponents];
    self.currentYearStr = [NSString stringWithFormat:@"%d",(int)nowComponents.year];
    self.currentMonthStr = [NSString stringWithFormat:@"%d",(int)nowComponents.month];
    NSString *timeKey = [NSString stringWithFormat:@"%@-%@",self.currentYearStr,self.currentMonthStr];
    
    //从缓存中取数据
    if ([self.cacheCashcalculateTimes objectForKey:timeKey]) {
        return [self.cacheCashcalculateTimes objectForKey:timeKey];
    }
    
    NSMutableArray *calendarModelArray = [NSMutableArray array ];
    
    //加载上个月的数据
    [self loadLastMonthDaysWithCalendarModelArray:calendarModelArray currentDate:monthDate currentComponents:nowComponents];
    
    //加载当月的数据
    NSInteger currentMonthLastDayWeek = [self loadCurrentMonthDaysWithCalendarModelArray:calendarModelArray currentDate:monthDate];
    
    //加载下月的数据
    [self loadNextMonthDaysWithCalendarModelArray:calendarModelArray currentDate:monthDate currentDayLastWeek:currentMonthLastDayWeek];
    
    //缓存数据
    [self.cacheCashcalculateTimes setObject:calendarModelArray forKey:timeKey];
    return calendarModelArray;
}
//加载上个月的数据
- (void)loadLastMonthDaysWithCalendarModelArray:(NSMutableArray *)calendarModelArray currentDate:(NSDate *)currentDate  currentComponents:(NSDateComponents *)currentComponents {

    NSDate *lastMonth =  [currentDate dayInTheLastMonth];//上个月
    NSDateComponents *lastMonthComponents = [lastMonth getYMDComponents];//获取上月的日期
    int lastDays = (int) [lastMonth getNumberOfDaysInCurrentMonth];//上月有多少天
    
    int beginIndex = 0;
    int needAddDays = 0;
    if (self.calendarScroViewBeginDay == NNCalendarScroViewBeginDaySunday) {
        beginIndex = 1;
        needAddDays = (int)currentComponents.weekday;
    }else if (self.calendarScroViewBeginDay == NNCalendarScroViewBeginDayMonday) {
        beginIndex = 0;
        needAddDays = currentComponents.weekday == 1 ? 6 :( (int)currentComponents.weekday - 2 );
    }else {
        return;
    }
    for (int i  = beginIndex; i < needAddDays; i++) {//可在此处添加上月的日期
        NNCalendarModel *calendarModel =  [NNCalendarModel calendarWithYear:[NSString stringWithFormat:@"%d",(int)lastMonthComponents.year]
                                                                      month:[NSString stringWithFormat:@"%d",(int)lastMonthComponents.month]
                                                                        day:[NSString stringWithFormat:@"%d",(int)(lastDays - (needAddDays - 1 - i))]
                                                                       week:[NSDate stringWithWeek:lastMonthComponents.weekday]];
        calendarModel.calendarModelDayType = NNCalendarModelTypeLastMonthDay;
        [calendarModelArray addObject:calendarModel];
    }


}
//加载当月的数据
- (NSInteger)loadCurrentMonthDaysWithCalendarModelArray:(NSMutableArray *)calendarModelArray currentDate:(NSDate *)currentDate  {
    //当月的最后一天是周几
    NSInteger currentMonthLastDayWeek = 0;
    
    NSDateComponents *todayComponents =  [[NSDate date] getYMDComponents];
    //获取该月的总天数
    NSInteger monthNum =   [currentDate getNumberOfDaysInCurrentMonth];
    for (int i = 0; i < monthNum; i++) {
        
        NSDate * nowDate =  [currentDate getDayInTheFollowingDay:i];
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
        NSDateComponents *components =  [[NSCalendar currentCalendar] components:NSYearCalendarUnit | NSMonthCalendarUnit  | NSDayCalendarUnit | NSWeekdayCalendarUnit fromDate:nowDate];
#pragma clang diagnostic pop
        NNCalendarModel *calendarModel = [[NNCalendarModel alloc]init];
        calendarModel.year  =   [NSString stringWithFormat:@"%d",(int)components.year];
        calendarModel.month =   [NSString stringWithFormat:@"%d",(int)components.month];
        calendarModel.day   =   [NSString stringWithFormat:@"%d",(int)components.day];
        calendarModel.week  =   [NSDate stringWithWeek:components.weekday];
        if (components.year == todayComponents.year &&
            components.month == todayComponents.month &&
            components.day == todayComponents.day) {
            calendarModel.calendarModelDayType = NNCalendarModelTypeToday;
        }
        if (i == monthNum - 1) {
            currentMonthLastDayWeek = components.weekday;
        }
        [calendarModelArray addObject:calendarModel];
    }
    return currentMonthLastDayWeek;
}
//加载下个月的数据
- (void)loadNextMonthDaysWithCalendarModelArray:(NSMutableArray *)calendarModelArray currentDate:(NSDate *)currentDate currentDayLastWeek:(NSInteger)currentMonthLastDayWeek {
    
    NSDate *nextMonth =  [currentDate dayInTheNextMonth];
    NSDateComponents *nextMonthComponents = [nextMonth getYMDComponents];//获取下月的日期
    NSInteger needAddDays = 0;
    if (self.calendarScroViewBeginDay == NNCalendarScroViewBeginDaySunday) {
        if (currentMonthLastDayWeek >= 7) {
            return;
        }
        needAddDays = 7 - currentMonthLastDayWeek;
    }else if(self.calendarScroViewBeginDay == NNCalendarScroViewBeginDayMonday) {
        if (currentMonthLastDayWeek == 1) {
            return;
        }
        needAddDays = 7 - (currentMonthLastDayWeek -1);
    }else {
        return;
    }
    for (int i  = 0; i < needAddDays; i++) {//可在此处添加上月的日期
        NNCalendarModel *calendarModel = [[NNCalendarModel alloc]init];
        calendarModel.year  =   [NSString stringWithFormat:@"%d",(int)nextMonthComponents.year];
        calendarModel.month =   [NSString stringWithFormat:@"%d",(int)nextMonthComponents.month];
        calendarModel.day   =   [NSString stringWithFormat:@"%d",(int)(i + 1)];
        calendarModel.week  =   [NSDate stringWithWeek:nextMonthComponents.weekday];

        calendarModel.calendarModelDayType = NNCalendarModelTypeNextMonthDay;
        [calendarModelArray addObject:calendarModel];
    }
}
- (void)resetScroll {
    int index = (int)self.backScroView.contentOffset.x / (int) [self backScroViewWidth];
    if (index == 1) {
        return;
    }
    [self sendMessageTodelegate];
    
    self.currentMonth = self.loadMonth;
    self.currentCalendarPageView.pageItems = self.moveCalendarPageView.pageItems;
    self.backScroView.contentOffset = CGPointMake([self backScroViewWidth], 0);
    [self updateSubviewFrame];
}
#pragma mark - public
- (void) sendMessageTodelegate {
    if ([self.delegate respondsToSelector:@selector(calendarScroView:year:month:)]) {
        [self.delegate calendarScroView:self year:self.currentYearStr month:self.currentMonthStr];
    }
}
- (void)calendarPageView:(NNCalendarPageView *)NNCalendarPageView itemDidClick:(NNCalendarModel *)model {
    if ([self.delegate respondsToSelector:@selector(calendarScroView:itemDid:)]) {
        [self.delegate calendarScroView:self itemDid:model];
    }
}
- (void)setNeedMonth:(NSString *)needMonth {
    _needMonth = needMonth;
    NSDateFormatter *formatter =  [[NSDateFormatter alloc]init];
    formatter.dateFormat = self.dateFormat;
    self.currentDate = [formatter dateFromString:needMonth];
}

- (void)setHeadViewColor:(UIColor *)headViewColor {
    _headViewColor = headViewColor;
    self.currentCalendarPageView.headViewBackColor = headViewColor;
    self.moveCalendarPageView.headViewBackColor = headViewColor;
}
- (void)setCalendarScroViewBeginDay:(NNCalendarScroViewBeginDay)calendarScroViewBeginDay {
    _calendarScroViewBeginDay = calendarScroViewBeginDay;
}
#pragma mark - 私有
- (CGFloat)backScroViewWidth {
    return self.backScroView.frame.size.width;
}
- (CGFloat)backScroViewHeight {
    return self.backScroView.frame.size.height;
}

#pragma mark - lazy load
- (UIScrollView *)backScroView {
    if (_backScroView == nil) {
        _backScroView = [[UIScrollView alloc]init];
        _backScroView.pagingEnabled = YES;
        _backScroView.showsVerticalScrollIndicator = NO;
        _backScroView.showsHorizontalScrollIndicator = NO;
        _backScroView.delegate = self;
        _backScroView.bounces = NO;
        
    }
    return _backScroView;
}
- (NNCalendarPageView *)currentCalendarPageView {
    if (_currentCalendarPageView == nil) {

        if (self.nibWithNibNameStr) {
            
            _currentCalendarPageView = [[NNCalendarPageView alloc]initWithNibNameStr:self.nibWithNibNameStr cellWithReuseIdentifier:self.cellWithReuseIdentifier calendarPageViewBeginDay:[self converDay]];
        }else {
              _currentCalendarPageView = [[NNCalendarPageView alloc]initWithRegisterClassName:self.registerClassName cellWithReuseIdentifier:self.cellWithReuseIdentifier calendarPageViewBeginDay:[self converDay]] ;
        }
        _currentCalendarPageView.delegate = self;
    }
    return _currentCalendarPageView;
}
- (NNCalendarPageView *)moveCalendarPageView {
    if (_moveCalendarPageView == nil) {

        if (self.nibWithNibNameStr) {
            _moveCalendarPageView = [[NNCalendarPageView alloc]initWithNibNameStr:self.nibWithNibNameStr cellWithReuseIdentifier:self.cellWithReuseIdentifier calendarPageViewBeginDay:[self converDay]];
        }else {
            _moveCalendarPageView = [[NNCalendarPageView alloc]initWithRegisterClassName:self.registerClassName cellWithReuseIdentifier:self.cellWithReuseIdentifier calendarPageViewBeginDay:[self converDay]];
        }
    }
    return _moveCalendarPageView;
}

- (NSMutableDictionary *)cacheCashcalculateTimes {
    if (_cacheCashcalculateTimes == nil) {
        _cacheCashcalculateTimes = [NSMutableDictionary dictionary ];
    }
    return _cacheCashcalculateTimes;
}

- (NNCalendarPageViewBeginDay)converDay {
    
    NNCalendarPageViewBeginDay begindDay = NNNCalendarPageViewSunday;
    if (self.calendarScroViewBeginDay == NNCalendarScroViewBeginDaySunday) {
        begindDay = NNNCalendarPageViewSunday ;
    }else if (self.calendarScroViewBeginDay == NNCalendarScroViewBeginDayMonday) {
        begindDay = NNCalendarPageViewMonday;
    }
    return begindDay;
}
@end
